package com.liuceng.zen.service;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.liuceng.zen.mapper.MemberWechatBindingMapper;
import com.liuceng.zen.mapper.WechatUserMapper;
import com.liuceng.zen.pojo.domain.MemberWechatBinding;
import com.liuceng.zen.pojo.domain.WechatUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by lijunhao on 16-11-23.
 */
@Service
public class WechatBindService extends BaseService<WechatUser>{
    private static final Integer SUCCESS = 1;
    private static final Integer FAILURE = 2;
    //请求access_token的链接
    private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token";
    //请求用户信息的链接
    private static final String GET_USERINFO_URL = "https://api.weixin.qq.com/sns/userinfo";
    //请求刷新access_token的链接
    private static final String REFERSH_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/refresh_token";

    @Value("${appid}")
    private String appid;
    @Value("${secret}")
    private String secret;

    @Autowired
    WechatUserMapper wechatUserMapper;
    @Autowired
    MemberWechatBindingMapper memberWechatBindingMapper;
    @Autowired
    MemberService memberService;
    @Autowired
    ApplicationService applicationService;

    /**
     * 函数名称: parseData
     * 函数描述: 将json字符串转换为Map<String, Object>结构
     *
     * @param   data
     * @return  Map<String, Object>
     */
    private static Map<String, Object> parseData(String data) {
        JSONObject jsonObject = JSONObject.parseObject(data);
        Map<String, Object> map = JSONObject.toJavaObject(jsonObject, Map.class);
        return map;
    }

    /**
     * 1:通过code向微信开放平台请求access_token
     *
     * @param code
     *
     */
    public Map<String,Object> getAccessToken(String code) {
        String params="appid="+appid+"&secret="+secret+"&code="+ code+"&grant_type=authorization_code";

        String resultJson = sendGet(GET_ACCESS_TOKEN_URL, params);
        Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储
        return map;
    }

    /**
     * 函数名称: get_userinfo
     *
     * 函数描述: 2: 通过access_token去获取用户的信息
     *
     * @param   access_token
     * @return  Map<String, String>
     */
    public Map<String,Object> getUserinfo(String access_token,String openid){
        StringBuffer params_userinfo=new StringBuffer()
                .append("access_token=").append(access_token)
                .append("&openid=").append(openid);
        String resultJson=sendGet(GET_USERINFO_URL,params_userinfo.toString());
        Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储
        if(map.size()>3){
            return map;
        }else{
            if(map.get("errcode").equals("42001")){
                //access_token超时,需要重新获得access_token超时，再请求用户信息
                Map<String,Object> map1= refreshAccessToken(access_token);
                String access_token2=map1.get("access_token").toString();
                String openid2=map1.get("openid").toString();
                //刷新以后重新获取用户的信息
                getUserinfo(access_token2,openid2);
            }
        }
        return map;
    }

    /**
     * 函数名称: refresh_access_token
     *
     * 函数描述: 3: access_token超时,使用refresh_token重新获得一个access_token
     *
     * @param   refresh_token
     * @return  Map<String, String>
     */
    public Map<String,Object> refreshAccessToken(String refresh_token){
        StringBuffer params_access=new StringBuffer()
                .append("appid=").append(appid)
                .append("&grant_type=refresh_token")
                .append("&refresh_token=").append(refresh_token);
        String resultJson=sendGet(REFERSH_ACCESS_TOKEN_URL,params_access.toString());
        Map<String,Object> map = parseData(resultJson);//将返回的json数据转换为Map结构存储
        return map;
    }

    /**
     * 向指定URL发送GET方法的请求
     *
     * @param url   发送请求的URL
     * @param param 请求参数，请求参数应该是 name1=value1&name2=value2 的形式。
     * @return URL 所代表远程资源的响应结果
     */
    public static String sendGet(String url, String param) {
        String result = "";
        BufferedReader in = null;
        try {
            String urlNameString = url + "?" + param;
            URL realUrl = new URL(urlNameString);
            // 打开和URL之间的连接
            URLConnection connection = realUrl.openConnection();
            // 设置通用的请求属性
            connection.setRequestProperty("accept", "*/*");
            connection.setRequestProperty("connection", "Keep-Alive");
            connection.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
            // 建立实际的连接
            connection.connect();
            // 获取所有响应头字段
            Map<String, List<String>> map = connection.getHeaderFields();

            // 定义 BufferedReader输入流来读取URL的响应
            in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
            String line;
            while ((line = in.readLine()) != null) {
                result += line;
            }
        } catch (Exception e) {
            LOG.error("发送GET请求出现异常！");
        }
        // 使用finally块来关闭输入流
        finally {
            try {
                if (in != null) {
                    in.close();
                }
            } catch (Exception e2) {
                LOG.error("关闭输入流出现异常！");
            }
        }
        return result;
    }

    /**
     * 根据code请求userinfo
     * @param code
     * @return
     */
    public Map<String, Object> getUserInfoMap(String code){
        Map<String, Object> map = new HashMap<>();
        Map<String, Object> userinfoMap = new HashMap<>();
        try{
            //1.根据code请求access_token
            map = getAccessToken(code);
            String access_token = map.get("access_token").toString();
            String openid = map.get("openid").toString();
            try{
                //2.使用access_token去请求用户信息
                userinfoMap = getUserinfo(access_token, openid);
            }catch (Exception e){
                LOG.error("使用access_token去请求用户信息出现异常!");
            }
        }catch (Exception e){
            LOG.error("根据code请求access_token出现异常!");
        }
        return userinfoMap;
    }

    /**
     * 插入客户信息
     * @param userinfoMap
     * @param memberId
     */
    @Transactional
    public Integer saveWeChatUserMessage(Map<String, Object> userinfoMap,Integer memberId){
        String unionid = userinfoMap.get("unionid").toString();
        //根据unionId查询已经绑定的客户信息
        WechatUser oldUser = selectWechatUserByUnionId(unionid);
        WechatUser wechatBind = new WechatUser();
        if(null==oldUser){
            wechatBind.setUnionid(unionid);
            wechatBind.setOpenid(userinfoMap.get("openid").toString());
            wechatBind.setCity(userinfoMap.get("city").toString());
            wechatBind.setNickname(userinfoMap.get("nickname").toString());
            wechatBind.setSex(Integer.valueOf(userinfoMap.get("sex").toString()));
            wechatBind.setProvince(userinfoMap.get("province").toString());
            wechatBind.setHeadimgurl(userinfoMap.get("headimgurl").toString());
            wechatBind.setCountry(userinfoMap.get("country").toString());
            wechatBind.setLanguage(userinfoMap.get("language").toString());
            String privilege = JSONArray.toJSONString(userinfoMap.get("privilege"));
            privilege = privilege.substring(1,privilege.length()-1);
            if(privilege!=""){
                wechatBind.setPrivilege(privilege);
            }
            //以前没有绑定则插入数据
            super.insert(wechatBind);
            return bindingWeiXinForMember(memberId,wechatBind.getId(),unionid);
        }else{
            oldUser.setUnionid(unionid);
            oldUser.setOpenid(userinfoMap.get("openid").toString());
            oldUser.setCity(userinfoMap.get("city").toString());
            oldUser.setNickname(userinfoMap.get("nickname").toString());
            oldUser.setSex(Integer.valueOf(userinfoMap.get("sex").toString()));
            oldUser.setProvince(userinfoMap.get("province").toString());
            oldUser.setHeadimgurl(userinfoMap.get("headimgurl").toString());
            oldUser.setCountry(userinfoMap.get("country").toString());
            oldUser.setLanguage(userinfoMap.get("language").toString());
            String privilege = JSONArray.toJSONString(userinfoMap.get("privilege"));
            privilege = privilege.substring(1,privilege.length()-1);
            if(privilege!=""){
                oldUser.setPrivilege(privilege);
            }
            //以前有绑定则更新数据
            super.update(oldUser);
            return bindingWeiXinForMember(memberId,oldUser.getId(),unionid);
        }
    }

    /**
     * 为客户绑定微信号
     * @param memberId
     * @param wechatId
     * @param unionid
     * @return
     */
    @Transactional
    public Integer bindingWeiXinForMember(Integer memberId,Integer wechatId,String unionid) {
        //查询该微信号有没有绑定
        MemberWechatBinding oldBinding = selectWechatBindingByUnionId(unionid);
        if(null!=oldBinding){
            return FAILURE;
        }else{
            MemberWechatBinding memberWechatRel = new MemberWechatBinding();
            memberWechatRel.setMemberId(memberId);
            memberWechatRel.setWechatId(wechatId);
            memberWechatRel.setBindAt(new Date());
            memberWechatBindingMapper.insertSelective(memberWechatRel);
            return SUCCESS;
        }
    }

    /**
     * 根据unionId查询已经绑定的客户信息
     * @param unionId
     * @return
     */
    public WechatUser selectWechatUserByUnionId(String unionId){
        Map<String,Object> map = new HashMap<>();
        map.put("unionid",unionId);
        return wechatUserMapper.selectWechatUserByUnionId(map);
    }

    /**
     * 查询该微信号有没有绑定
     * @param unionId
     * @return
     */
    public MemberWechatBinding selectWechatBindingByUnionId(String unionId){
        Map<String,Object> map = new HashMap<>();
        map.put("unionid",unionId);
        return memberWechatBindingMapper.selectWechatBindingByUnionId(map);
    }
    /**
     * 根据账号id查询所有绑定该账号的微信
     * @param memberId
     * @return
     */
    public List<WechatUser> getBindedWechat(Integer memberId){
        Map<String,Object> map = new HashMap<>();
        map.put("memberId",memberId);
        return wechatUserMapper.getBindedWechat(map);
    }

    /**
     * 解除微信绑定
     * @param wechatId
     * @return
     */
    public Integer removeBinding(Integer wechatId){
        return memberWechatBindingMapper.deleteByWechatId(wechatId);
    }
}
